home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / library / ix_timer.c < prev    next >
C/C++ Source or Header  |  1995-05-27  |  4KB  |  132 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: ix_timer.c,v 1.3 1994/06/19 15:13:28 rluebbert Exp $
  21.  *
  22.  *  $Log: ix_timer.c,v $
  23.  *  Revision 1.3  1994/06/19  15:13:28  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  27.  *  Initial revision
  28.  *
  29.  */
  30.  
  31. #define KERNEL
  32. #include "ixemul.h"
  33. #include "kprintf.h"
  34.  
  35. /*
  36.  * this is the interrupt code that distributes those itimer signals and
  37.  * collects resource information
  38.  */
  39.  
  40. /*
  41.  * For all you "moralists" out there in Amiga land...
  42.  * This code uses exec private information about what the stack frame looks
  43.  * like inside an interrupt. However, this information is used read-only, and
  44.  * it really doesn't matter whether it will be wrong in the future, in that
  45.  * case system-time will be measured in other ways, but so what ? ;-))
  46.  */
  47.  
  48. /* executing in ROM is considered "system" ... */
  49. #define is_user(pc) (pc < 0xf80000 || pc > 0xffffff)
  50. extern struct ExecBase *SysBase;
  51.  
  52. int ix_timer (char *foobar, ...) __attribute__ ((interrupt));
  53.  
  54. /*
  55.  * by specifying the function as taking varargs parameter, we force gcc
  56.  * to generate a framepointer...
  57.  */
  58.  
  59. int
  60. ix_timer (char *foobar, ...)
  61. {
  62.   register struct Task    *t_pass    asm ("a1");
  63.   struct Task        *me;
  64.   struct user        *p;
  65.   /* not necessarily "me" */
  66.   struct Task        *current_task    = SysBase->ThisTask;
  67.   u_int            current_pc;
  68.   register u_int    a5 asm ("a5");
  69.   u_int            sp;
  70.   struct itimerval    *tim;
  71.   
  72.   me = t_pass;
  73.   p = (struct user *) me->tc_TrapData;
  74.  
  75.   /* find out value of sp on invocation of this function. This is easy,
  76.    * since gcc generates a 
  77.    *   link a5,#..
  78.    * at the beginning. So we find sp with a5+4
  79.    */
  80.   sp = a5+4;
  81.  
  82.   tim = p->u_timer;
  83.  
  84.   /* The main work. Decrement the timers, and if they hit zero, generate
  85.    * the approprate signal */
  86.  
  87.   /* real timer counts in real time */
  88.   if (timerisset (&tim->it_value) && !itimerdecr (tim, ITIMER_RESOLUTION))
  89.     _psignal (me, SIGALRM);
  90.   ++tim;
  91.  
  92.   /* virtual timer only counts, when current_task == me AND the task is
  93.    * not executing in system time. To get at the current PC, remember (or learn;-))
  94.    * that the stack in an interrupt handler looks like follows:
  95.    *   0(sp)  rts into ExitIntr
  96.    *   4(sp),8(sp),12(sp),16(sp),20(sp),24(sp) -> d0/d1/a0/a1/a5/a6
  97.    *    now the stuff for the correct rte instruction
  98.    *   28(sp) -> SR
  99.    *   30(sp) -> PC <- that's what we're interested in
  100.    */
  101.     /* heuristics for 2.0.. */
  102.     current_pc = *(u_int *)(sp + 46);
  103.  
  104.   if ((me == current_task) && is_user (current_pc) && timerisset(&tim->it_value) &&
  105.       !itimerdecr (tim, ITIMER_RESOLUTION))
  106.     _psignal (me, SIGVTALRM);
  107.   ++tim;
  108.  
  109.   /* profiling timer, runs while this process is executing, no matter
  110.    * whether in system time or not */
  111.   if ((me == current_task) &&timerisset(&tim->it_value) &&
  112.       !itimerdecr (tim, ITIMER_RESOLUTION))
  113.     _psignal (me, SIGPROF);
  114.  
  115.   /* now that we're done with the timers, if this is our task executing,
  116.    * update it's rusage fields */
  117.   if (me == current_task)
  118.     {
  119.       struct timeval *tv;
  120.       tv = is_user (current_pc) ? &p->u_ru.ru_utime : &p->u_ru.ru_stime;
  121.       tv->tv_usec += ITIMER_RESOLUTION;
  122.       if (tv->tv_usec >= 1000000)
  123.     {
  124.       tv->tv_usec -= 1000000; /* - is much cheaper than % */
  125.       tv->tv_sec ++;
  126.     }
  127.     }
  128.   if (p->u_prof.pr_scale)
  129.       addupc (current_pc, &p->u_prof, 1);
  130. return 0;
  131. }
  132.